package net.minecraft.entity.player.Really.Client.utils.proxy;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import net.minecraft.client.multiplayer.GuiConnecting;
import net.minecraft.entity.player.Really.Client.utils.Helper;
import net.minecraft.entity.player.Really.Client.utils.proxy.ProxySocket;
import net.minecraft.util.ChatComponentText;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

public class TransparentProxy {
   private final int listenerPort;
   private Logger logger = LogManager.getLogger("AC-Proxy");
   private ServerSocket listener;
   private Socket client;
   private Socket server;
   private Exception failReason;
   public boolean failed = false;
   private boolean ready = false;
   private boolean running = true;

   public TransparentProxy(int listenerPort) {
      this.listenerPort = listenerPort;
   }

   public void start(String proxy, int proxyPort, String ip, int port) throws Exception {
      this.failed = false;
      this.ready = false;
      if(this.running) {
         this.stop();
      }

      try {
         this.logger.info("Starting Listener...");
         this.listener = new ServerSocket(this.listenerPort, 1);
         this.listener.setReuseAddress(true);
         this.logger.info("Listener started!");
         (new Thread(() -> {
            try {
               this.logger.info("Waiting for connection...");
               this.ready = true;
               this.client = this.listener.accept();
               this.client.setTcpNoDelay(true);
               this.logger.info("Connection incoming!");
               this.running = true;
               this.logger.info("Connecting you via Proxy...");
               this.server = ProxySocket.connectOverProxy(proxy, proxyPort, ip, port);
               this.logger.info("Connected!");
               (new Thread(() -> {
                  try {
                     byte[] buffer = new byte[4096];
                     InputStream in = this.client.getInputStream();
                     OutputStream out = this.server.getOutputStream();

                     while(this.running) {
                        int read = in.read(buffer);
                        if(read <= 0) {
                           throw new IOException();
                        }

                        out.write(buffer, 0, read);
                     }
                  } catch (Exception var5) {
                     this.failReason = var5;
                     this.failed = true;
                  }

               }, "AC-Proxy-Send")).start();
               (new Thread(() -> {
                  try {
                     byte[] buffer = new byte[4096];
                     InputStream in = this.server.getInputStream();
                     OutputStream out = this.client.getOutputStream();

                     while(this.running) {
                        int read = in.read(buffer);
                        if(read <= 0) {
                           throw new IOException();
                        }

                        out.write(buffer, 0, read);
                     }
                  } catch (Exception var5) {
                     this.failReason = var5;
                     this.failed = true;
                  }

               }, "AC-Proxy-Recv")).start();
               this.logger.info("Proxy started!");
            } catch (Exception var9) {
               var9.printStackTrace();
               this.failReason = var9;
               this.failed = true;
               if(Helper.mc.currentScreen != null && Helper.mc.currentScreen instanceof GuiConnecting && ((GuiConnecting)Helper.mc.currentScreen).networkManager != null) {
                  ((GuiConnecting)Helper.mc.currentScreen).networkManager.closeChannel(new ChatComponentText("Proxy failure"));
               }

               try {
                  this.client.close();
               } catch (IOException var8) {
                  ;
               }

               try {
                  this.server.close();
               } catch (IOException var7) {
                  ;
               }
            }

         }, "AC-Proxy")).start();
      } catch (IOException var6) {
         this.failReason = var6;
         this.failed = true;
      }

   }

   public void stop() {
      if(this.listener != null) {
         try {
            this.listener.close();
         } catch (IOException var2) {
            ;
         }
      }

      this.listener = null;
      this.running = false;
   }

   public boolean isRunning() {
      return this.running;
   }

   public boolean isReady() {
      return this.ready;
   }

   public boolean hasFailed() {
      return this.failed;
   }

   public Exception getFailReason() {
      return this.failReason;
   }
}
